#pragma once

#include "../config.h"

#include <mysql.h>
#include <mysql++.h>

class DBPacket : public Packet
{
public:

	DBPacket(Register* reg = NULL);
	DBPacket(uint16 opcode, Register* reg = NULL);
	DBPacket(const DBPacket &r);
	
	virtual ~DBPacket() {}
	
	DBPacket& operator= (const DBPacket& r);

	uint16 GetState() const		{ return _state; }
	void SetState(uint16 state) { _state = state; }

	const char* GetSQL() const 	{ return _sql; }
	bool IsSimpleQuery() const	{ return _is_simple_query; }

	void SimpleQuery(const char *fmt, ...);
	void Query(const char *fmt, ...);

	mysqlpp::StoreQueryResult& GetResult()						{ return _query_result; }
	void SetResult(const mysqlpp::StoreQueryResult &result)		{ _query_result = result; }

	mysqlpp::SimpleResult& GetSimpleResult()					{ return _simple_query_result; }
	void SetSimpleResult(const mysqlpp::SimpleResult &result)	{ _simple_query_result = result; }
	
	virtual void EncodePacket(){};
	virtual bool DecodePacket(const uint8* data, const uint16 size){ return false;}

private:

	uint16 _state;
	bool   _is_simple_query;

	static const int SQL_MAX_SIZE = 1024;
	char   _sql[SQL_MAX_SIZE];

	mysqlpp::StoreQueryResult _query_result;
	mysqlpp::SimpleResult     _simple_query_result;
};

class DBOperator : public Thread
{
	friend class SingleTon<DBOperator>;

	DBOperator();

	virtual ~DBOperator();
	virtual int _Prepare();
	virtual int _Kernel();
	virtual int _Finish();

public:

	void AddRequest(DBPacket& packet);
	
	int SimpleQuery(mysqlpp::SimpleResult &result, const char *fmt, ...);
	
	int Query(mysqlpp::StoreQueryResult &result, const char *fmt, ...);

private:

	std::string _host;
	uint16	    _port;

	std::string _user;
	std::string _password;
	std::string _database;

	ThreadSafeBlockQueue<DBPacket> _request_queue;
	mysqlpp::Connection _mysql_sync;
	mysqlpp::Connection _mysql_async;

	static const uint32 MAX_KEEP_TIME = 25000;
	uint64 connected_timestamp_sync;
	uint64 connected_timestamp_async;
};

#define sDBOperator Singleton<DBOperator>::Instance()